﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
using System.Reflection;
using WyUnity.Utility;
using WyUnity.Data.TableMapper;

namespace WyUnity.Data.Query
{
	public interface IField
	{
		string FieldName { get; }
		WhereClip Like(string likestring);
		WhereClip In(params object[] objs);
		WhereClip IsNull();
		WhereClip IsNotNull();
		IOrderByClip Arc { get; }
		IOrderByClip Desc { get; }
	}
	public abstract class FieldBase : IField
	{
		public abstract string FieldName { get; }
		public abstract WhereClip Like(string likestring);
		public abstract WhereClip In(params object[] objs);
		public abstract WhereClip IsNull();
		public abstract WhereClip IsNotNull();
		public abstract IOrderByClip Arc { get; }
		public abstract IOrderByClip Desc { get; }

		#region 运算符重载
		public static WhereClip operator >(FieldBase c1, FieldBase c2)
		{
			return new WhereFieldtoField(c1.FieldName, SqlCompareOperation.Greater, c2.FieldName);
		}
		public static WhereClip operator >(FieldBase c1, object c2)
		{
			return new Where(c1.FieldName, SqlCompareOperation.Greater, c2);
		}
		public static WhereClip operator >=(FieldBase c1, FieldBase c2)
		{
			return new WhereFieldtoField(c1.FieldName, SqlCompareOperation.GreaterOrEqual, c2.FieldName);
		}
		public static WhereClip operator >=(FieldBase c1, object c2)
		{
			return new Where(c1.FieldName, SqlCompareOperation.GreaterOrEqual, c2);
		}
		public static WhereClip operator <(FieldBase c1, FieldBase c2)
		{
			return new WhereFieldtoField(c1.FieldName, SqlCompareOperation.Less, c2.FieldName);
		}
		public static WhereClip operator <(FieldBase c1, object c2)
		{
			return new Where(c1.FieldName, SqlCompareOperation.Less, c2);
		}
		public static WhereClip operator <=(FieldBase c1, FieldBase c2)
		{
			return new WhereFieldtoField(c1.FieldName, SqlCompareOperation.LessOrEqual, c2.FieldName);
		}
		public static WhereClip operator <=(FieldBase c1, object c2)
		{
			return new Where(c1.FieldName, SqlCompareOperation.LessOrEqual, c2);
		}
		public static WhereClip operator ==(FieldBase c1, FieldBase c2)
		{
			return new WhereFieldtoField(c1.FieldName, SqlCompareOperation.Equal, c2.FieldName);
		}
		public static WhereClip operator ==(FieldBase c1, object c2)
		{
			return new Where(c1.FieldName, SqlCompareOperation.Equal, c2);
		}
		public static WhereClip operator !=(FieldBase c1, FieldBase c2)
		{
			return new WhereFieldtoField(c1.FieldName, SqlCompareOperation.NotEqual, c2.FieldName);
		}
		public static WhereClip operator !=(FieldBase c1, object c2)
		{
			return new Where(c1.FieldName, SqlCompareOperation.NotEqual, c2);
		}
		#endregion

		public override int GetHashCode()
		{
			return FieldName.GetHashCode();
		}
		public override bool Equals(object obj)
		{
			if (obj == null) return false;
			if (!(obj is FieldBase)) return false;
			return FieldName == (obj as FieldBase).FieldName;
		}
	}
	public class Field<T> : FieldBase
	{
		private string _field;

		public Field(System.Linq.Expressions.Expression<Func<T, object>> propertyExpression)
		{
			var ebody = propertyExpression.Body;
			if (ebody is UnaryExpression)
			{
				var bbody = ebody as UnaryExpression;
				if (bbody.NodeType == ExpressionType.Convert)
				{
					ebody = bbody.Operand;
				}
				else
				{
					ebody = null;
				}
			}
			var body = ebody as System.Linq.Expressions.MemberExpression;
			if (body == null) throw new NotSupportedException("在定义Where条件时，只能使用返回单一属性的Lambda表达式");
			//Log.Default.Debug(body.Member.Name);

			_field = GetMapField(body);
		}

		public Field(System.Linq.Expressions.Expression<Func<T, ValueType>> propertyExpression)
		{

			var ebody = propertyExpression.Body;
			if (ebody is UnaryExpression)
			{
				var bbody = ebody as UnaryExpression;
				if (bbody.NodeType == ExpressionType.Convert)
				{
					ebody = bbody.Operand;
				}
				else
				{
					ebody = null;
				}
			}
			var body = ebody as System.Linq.Expressions.MemberExpression;
			if (body == null) throw new NotSupportedException("在定义Where条件时，只能使用返回单一属性的Lambda表达式");
			//Log.Default.Debug(body.Member.Name);

			_field = GetMapField(body);
		}

		public override string FieldName
		{
			get { return _field; }
		}

		private static string GetMapField(MemberExpression exp)
		{
			var member = GetPropMember(exp);
			var map = member.GetSingleAttribute<MapAttribute>();
			if (map == null || string.IsNullOrEmpty(map.Name)) return member.Name;
			return map.Name;
		}
		private static MemberInfo GetPropMember(MemberExpression exp)
		{
			return exp.Member;
		}


		public override WhereClip Like(string likestring)
		{
			return new Where(_field, SqlCompareOperation.Like, likestring);
		}
		public override WhereClip In(params object[] objs)
		{
			return new Where(_field, SqlCompareOperation.In, objs);
		}
		public override WhereClip IsNull()
		{
			return new Where(_field, SqlCompareOperation.IsNull, null);
		}
		public override WhereClip IsNotNull()
		{
			return new Where(_field, SqlCompareOperation.IsNotNull, null);
		}
		public override IOrderByClip Arc
		{
			get { return new OrderClip(_field, SQLOrderSeq.ASC); }
		}
		public override IOrderByClip Desc
		{
			get { return new OrderClip(_field, SQLOrderSeq.DESC); }
		}
	}
}
